#include <ani.h>
#include <array>
#include <iostream>

static ani_object createResult([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object object){
    
    ani_object result_obj = {};

    static const char *className = "ani_template.Result";
    ani_class cls;
    if (ANI_OK != env->FindClass(className, &cls)) {
        std::cerr << "Not found '" << className << "'" << std::endl;
        return result_obj;
    }

    //查找构造函数，如果没有重载，可以直接传递 nullptr
    ani_method ctor;
    if (ANI_OK != env->Class_FindMethod(cls, "<ctor>", nullptr, &ctor)){
        std::cerr << "get ctor Failed'" << className << "'" << std::endl;
        return result_obj;
    }

    //从C++的string (大多数情况是UTF8) 构造一个 string
    //创建 result<string,Error> string
    std::string name = "/tmp/";
    ani_string result_string{};
    env->String_NewUTF8(name.c_str(), name.size(), &result_string);


    //创建 result<string,Error> 的 Error
    ani_class errCls;
    if (ANI_OK != env->FindClass("std.core.NullPointerError", &errCls)) {
        std::cerr << "Not found '" << className << "'" << std::endl;
        return result_obj;
    }
    
    std::cerr << "found '" << className << "'" << std::endl;
    ani_object errObj;
    //查找构造函数，如果没有重载，可以直接传递 nullptr
     ani_method errCtor;
     if (ANI_OK != env->Class_FindMethod(errCls, "<ctor>", nullptr, &errCtor)){
         std::cerr << "get errCtor Failed'" << "std.core.NullPointerError" << "'" << std::endl;
         return result_obj;
     }
     std::cerr << "get errCtor'" << "std.core.NullPointerError" << "'" << std::endl;
     
     //创建一个 Error  的实例
     if (ANI_OK != env->Object_New(errCls, errCtor, &errObj)){
        std::cerr << "Create Object Failed'" << "std.core.NullPointerError" << "'" << std::endl;
        return result_obj;
    }

    //创建一个 Result 的实例，第一个参数是 string, 第二个参数是 Error new Result<string,Error>(result_string, errObj)
    if (ANI_OK != env->Object_New(cls, ctor, &result_obj, result_string, errObj)){
        std::cerr << "Create Object Failed'" << className << "'" << std::endl;
        return result_obj;
    }
    return result_obj;
}


ANI_EXPORT ani_status ANI_Constructor(ani_vm *vm, uint32_t *result)
{
    ani_env *env;
    if (ANI_OK != vm->GetEnv(ANI_VERSION_1, &env)) {
        std::cerr << "Unsupported ANI_VERSION_1" << std::endl;
        return ANI_ERROR;
    }

    static const char *className = "ani_template.ETSGLOBAL";
   
    ani_class cls;
    if (ANI_OK != env->FindClass(className, &cls)) {
        std::cerr << "Not found '" << className << "'" << std::endl;
        return ANI_ERROR;
    }

    std::array methods = {
        ani_native_function {"createResult", nullptr, reinterpret_cast<void *>(createResult)},
    };

    std::cout << "Start bind native methods to '" << className << "'" << std::endl;

    if (ANI_OK != env->Class_BindNativeMethods(cls, methods.data(), methods.size())) {
        std::cerr << "Cannot bind native methods to '" << className << "'" << std::endl;
        return ANI_ERROR;
    };
    std::cout << "Finish bind native methods to '" << className << "'" << std::endl;

    *result = ANI_VERSION_1;
    return ANI_OK;
}